package cn.ygh.bbo.system.sdk.shiro;

import cn.ygh.bbo.common.utils.Md5Utils;
import cn.ygh.bbo.framerwork.web.WebUtils;
import cn.ygh.bbo.system.bean.*;
import cn.ygh.bbo.system.service.*;
import cn.ygh.bbo.system.utils.PermissionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 自定义权限控制
 * @author ygh
 * @Type UserRealm.java
 * @Desc
 * @date 2019/9/29
 * @Version V2.0
 */
public class UserRealm extends AuthorizingRealm {

    @Autowired(required = false)
    AdminService adminService;

    @Autowired(required = false)
    RoleService roleService;

    @Autowired(required = false)
    PermissionService permissionService;

    @Autowired(required = false)
    LoginLogService loginLogService;

    @Autowired(required = false)
    DataFilterService dataFilterService;

    /**
     * 权限控制
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        Admin admin= (Admin) principalCollection.fromRealm(getName()).iterator().next();
        List<Role> roles =admin.getRoles();
        if (roles.size()==0){
            return info;
        }
        //超管拥有所有权限
        if (PermissionUtils.isAdmin(roles)){
            info.addStringPermission("*:*:*");
            info.addRole("*");
            return info;
        }
        //角色控制
        info.addRoles(roles.stream().map(e->e.getName()).collect(Collectors.toList()));
        //按钮权限控制
        info.addStringPermissions(admin.getPermissions());
        return info;
    }

    /**
     * 登陆控制
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken=(UsernamePasswordToken) token;
        //账号密码判断
        Admin adminDb=adminService.getByUsername(usernamePasswordToken.getUsername());
        if (adminDb==null){
            throw new AuthenticationException("该账号不存在");
        }
        if(!adminDb.getStatus().equals(0)){
            throw new AuthenticationException("该账号已被冻结,请联系一下相关人员");
        }
        String password=new String(usernamePasswordToken.getPassword());
        if (!adminDb.getPassword().equals(Md5Utils.encodePassword(password))){
            throw new AuthenticationException("密码错误");
        }
        //验证成功日志添加
        LoginLog loginLog = new LoginLog(
                adminDb.getUsername() //用户名
                ,adminDb.getId() //管理员序号
                ,WebUtils.getIp() //Ip
                ,new Date() //创建时间
        );
        loginLogService.save(loginLog);
        //添加角色列表
        List<Role> roles = roleService.listfindByAdminId(adminDb.getId());
        adminDb.setRoles(roles);
        //超管直接返回 无数据权限过滤
        if (PermissionUtils.isAdmin(adminDb.getRoles())){
            return new SimpleAuthenticationInfo(adminDb,password,getName());
        }
        //数据过滤权限列表
        List<Integer>roleIds=roles.stream().map(e->e.getId()).collect(Collectors.toList());
        List<DataFilter>dataFilterList=dataFilterService.listfindByRoleIds(roleIds);
        Map<String,String>dataFilters=new HashMap<>();
        dataFilterList.forEach(e->dataFilters.put(e.getTableName(), e.getDataFilter()));
        adminDb.setDataFilters(dataFilters);
        //按钮操作权限
        List<Permission> permisstions = permissionService.listfindByRoles(roles);
        List<String>permissionList=new ArrayList<>();
        for (Permission permission:permisstions){
            if (StringUtils.isNotBlank(permission.getPerms())){
                String[]perms=permission.getPerms().split(",");
                permissionList.addAll(Arrays.asList(perms));
            }
        }
        adminDb.setPermissions(permissionList);
        return new SimpleAuthenticationInfo(adminDb,password,getName());
    }
}
